package com.t235.gc.configs.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.t235.gc.configs.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableWebSecurity//此注解的功能 指定为Spring Security类
@Slf4j
public class MyWebSecurityConfigs extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;
    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder(10);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //定义内存中的用户名密码与访问权限
        auth.userDetailsService(userService);//每次用户登入的时候就会调用到userService中的loadUserByUsername(Username)方法
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //定义访问权限的页面admin开头的页面只有ADMIN权限用户可以访问,user开头的页面ADMIN与USER权限的用户可以访问,
        //db开头的页面ADMIN与DBA权限角色可以访问
        http.authorizeRequests()
                .antMatchers("/api/partners/admin/**","/api/goods-order/admin/**"
                ,"/api/goods-category/admin/**","/api/goods/admin/**","/api/device/admin/**","/api/manager/admin/**").permitAll()
               // .access("@rbacService.hasPermission(request,authentication)")//添加可以访问的角色
                .antMatchers("/login_page.html","/good/login").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/login_page.html")//自定义登入页面
                .loginProcessingUrl("/login")//系统自带登入页面 没有权限就跳转到login页面
                //.usernameParameter("name")//用户name名默认为username 修改为name
                //.passwordParameter("passwd")//密码name名默认为password 修改为passwd
                .successHandler(new AuthenticationSuccessHandler() {
                    //登入成功的操作 可以跳转页面 可以返回json数据 演示json数据

                    public void onAuthenticationSuccess(HttpServletRequest req,
                                                        HttpServletResponse resp,
                                                        Authentication auth)
                            throws IOException, ServletException {
                Object principal=auth.getPrincipal();
                        //resp.setContentType("application/json;charset=utf-8");
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        resp.setStatus(200);
                        Map<String,Object> map=new HashMap<>();
                        map.put("status",200);
                        map.put("msg","首页");
                        ObjectMapper om=new ObjectMapper();
                        //resp.sendRedirect("/index");
                        out.print(om.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {
                    //登入失败 处理方法 可以跳转页面 可以返回json数据 演示json数据
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest rep,
                                                        HttpServletResponse resp,
                                                        AuthenticationException e)
                            throws IOException, ServletException {
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        resp.setStatus(401);
                        Map<String,Object> map =new HashMap<>();
                        map.put("status",401);
                        if(e instanceof LockedException){
                            map.put("msg","账号被锁定,登入失败");
                        }else if(e instanceof BadCredentialsException){
                            map.put("msg","账户名或密码输入错误,登入失败");
                        }else if(e instanceof DisabledException){
                            map.put("msg","账号被禁用,登入失败");
                        }else if(e instanceof AccountExpiredException){
                            map.put("msg","账号过期,登入失败");
                        }else if(e instanceof CredentialsExpiredException){
                            map.put("msg","密码过期,登入失败");
                        }else{
                            map.put("msg","登入失败");
                        }
                        ObjectMapper om=new ObjectMapper();
                        out.print(om.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .and()
                .cors()
                .and()
                .csrf()
                .disable()
                .authorizeRequests();
                http.headers()//请求头设置
                    .frameOptions();//允许嵌套页面
                //.formLogin().disable();
                /*.and()
                .logout()//开启登出配置
                .logoutUrl("/logout")//注销请求为logout
                .clearAuthentication(true)//是否清除身份证人的信息 true清除 默认true
                .invalidateHttpSession(true)//是否使session失效 true失效 默认true
                .addLogoutHandler(new LogoutHandler() {
                    @Override
                    public void logout(HttpServletRequest req,
                                       HttpServletResponse resp,
                                       Authentication auth) {
                        //可以在此方法类完成一些清除朝着如cookie
                    }
                })
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest rep,
                                                HttpServletResponse resp,
                                                Authentication auth) throws IOException, ServletException {
                        //注销成功后在此方法中完成一些业务逻辑
                        resp.sendRedirect("/login_page");//重定向到登入页面
                    }
                })
                .permitAll()
                .and()
                .csrf()
                .disable();*/
        //http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);//关闭Session
        //开启过滤器 进入过滤器必须包含token 前置增强
        //http.addFilterBefore(new JWTAuthorizationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);

    }
}
